package com.cyy.model

import cn.hutool.core.util.ReflectUtil
import com.jfinal.kit.Kv
import com.jfinal.plugin.activerecord.Config
import com.jfinal.plugin.activerecord.Db
import com.jfinal.plugin.activerecord.DbKit
import com.jfinal.plugin.activerecord.DbPro
import com.jfinal.plugin.activerecord.dialect.*
import com.jfinal.template.Directive
import com.jfinal.template.Engine
import com.jfinal.template.Env
import com.jfinal.template.expr.ast.ExprList
import com.jfinal.template.io.Writer
import java.sql.Connection
import java.util.*
import javax.sql.DataSource
import kotlin.collections.ArrayList

//import javax.sql.DataSource

object Constants {
    fun closeDb(ds: DataSource) {
        try {
            ds.connection.close()
            println("db connection close success")
        } catch (e: Exception) {
            println("db connection close fail :${e}")
        }
    }

    /**
     *  DelKey 判断Kv是否包含key=name的项，如果存在，则删除
     * @author cyy
     * @param
     */
    fun DelKey(map: Kv, vararg name: String): Kv {
        arrayOf(name).forEach {
            if (map.containsKey(name)) {
                map.delete(name)
            }
        }
        return map
    }

    /**setActiveDb 当dataSource更改后,更新RecordDb
     * @param ds gmodel.dataSource.value
     * @param configName "config"
     */
    fun setRecordDb(configName: String, ds: DataSource, dialect: Dialect): DbPro {
        val config = Config(configName, ds, dialect)
        try {
            DbKit.addConfig(config)
        } catch (e: Exception) {
            println("""DbKit.addConfig(config) failed or the config is already exist""")
        }
        return Db.use(configName)
    }

    fun getSharedObject(engine: Engine): Collection<*> {
        val map = ReflectUtil.invoke(engine.getEngineConfig(), "getSharedObjectMap") as Map<String, Any>
        return map.values
    }

    fun getSharedObjectMap(engine: Engine): Map<String, Any> {
        val map = ReflectUtil.invoke(engine.getEngineConfig(), "getSharedObjectMap") as Map<String, Any>
        return map
    }

    fun addSharedObject(engine: Engine, kv: Kv) {
        val ec = engine.getEngineConfig()
        val mapOld = ReflectUtil.invoke(ec, "getSharedObjectMap") as Map<String, Any>
        val sharedObjectMap = ReflectUtil.getField(ec.javaClass, "sharedObjectMap")
        sharedObjectMap.isAccessible = true

        var mapNew = Constants.DelKey(Kv().set(mapOld), "DbPro", "Db", "gmodel")
        sharedObjectMap.set(ec, mapNew)

        try {
//            kv.forEach { t, u -> engine.addSharedObject(t.toString(), u) }

            kv.forEach { t, u -> ec.addSharedObject(t.toString(), u) }

//            engine.addSharedObject("jDbPro", jDbPro)
//            engine.addSharedObject("jDb", Db())
//            engine.addSharedObject("gmodel", gmodel)
        } catch (e: Exception) {
            println("""engine.addSharedObject failed ${e}""")
        }
    }

    /**
     * 将传入的所有列表中的元素清空
     * @param ArrayList 列表数组
     * @return 将传入的所有列表中的元素清空后返回
     */
    fun clearLists(vararg lists: ArrayList<*>): ArrayList<*> {
        lists.forEach {
            it.clear()
        }
        return arrayListOf(lists)
    }
}

enum class DbType {
    /**
     * The horizontal (right <-> left) orientation
     */
    HORIZONTAL,

    /**
     * The vertical (top <-> bottom) orientation
     */
    VERTICAL
}


class NowDirective : Directive() {
    override fun exec(env: Env?, scope: com.jfinal.template.stat.Scope?, writer: Writer?) {
        write(writer, Date().toString())
    }
}

class Demo : Directive() {
    // ExprList 代表指令参数表达式列表
    override fun setExprList(exprList: ExprList?) {
        // 在这里可以对 exprList 进行个性化控制
        super.setExprList(exprList)
    }

    override fun exec(env: Env?, scope: com.jfinal.template.stat.Scope?, writer: Writer?) {
        write(writer, "body 执行前\n")
        stat.exec(env, scope, writer)  // 执行 body
        write(writer, "body 执行后\n")
    }

    override fun hasEnd(): Boolean {
        return true  // 返回 true 则该指令拥有 #end 结束标记
    }
}